import TJavaLib.*;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.BufferedReader;
import java.util.Random;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
import java.text.DecimalFormat;

public class TResultView extends JPanel {
	private TNetwork network;
	private int simW, simH, xMoveView, yMoveView;
	private double ratioW, ratioH, xZoom, yZoom, netW, netH;
	private TList net;
	private Random random;
	private JFrame frame;
	private boolean movingView;
	
	public TResultView(TNetwork network, String Title) {
		frame = new JFrame(Title);
		frame.add(this);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		setPreferredSize(new Dimension(700, 610));
		setBackground(Color.WHITE);
		
		this.network = network;
		net = network.getNetwork();
		netW = network.getDepW();
		netH = network.getDepH();
		xZoom = netW / 2;
		yZoom = netH / 2;
		movingView = false;
		
		//Resize response
		addComponentListener(new ComponentAdapter() {
			public void componentResized(ComponentEvent evt) {	resultViewResized(evt); } });
		
		addMouseWheelListener(new MouseWheelListener() {
			public void mouseWheelMoved(MouseWheelEvent evt) { netViewMouseWheeled(evt); }
		});
		
		addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent evt) { netViewMousePressed(evt); }
			public void mouseReleased(MouseEvent evt) { netViewMouseReleased(evt); }
		});
	}

	public void resultViewResized(ComponentEvent evt) {
		resizedResponse();
	}
	
	public void netViewMousePressed(MouseEvent evt) {
		if (evt.getButton() == MouseEvent.BUTTON1) {
			movingView = true;
			xMoveView = evt.getX();
			yMoveView = evt.getY();
		}
	}
	
	public void netViewMouseReleased(MouseEvent evt) {
		if (movingView) {
			movingView = false;
			double dx = -evt.getX() + xMoveView;
			double dy = evt.getY() - yMoveView;
			xZoom += dx/ratioW;
			if (xZoom < netW/2) xZoom = netW/2;
      if (xZoom+netW/2 > network.getDepW()) xZoom = network.getDepW()-netW/2;
      yZoom += dy/ratioH;
      if (yZoom < netH/2) yZoom = netH/2;
      if (yZoom+netH/2 > network.getDepH()) yZoom = network.getDepH()-netH/2;
			repaint();
		}
	}
	
	public void netViewMouseWheeled(MouseWheelEvent evt) {
		if (evt.getScrollAmount() != 0) {
      double zoom = (evt.getWheelRotation() < 0)?0.9:1.1;
      netW *= zoom;
      if (netW > network.getDepW())
      	netW = network.getDepW();
      netH *= zoom;
      if (netH > network.getDepH())
      	netH = network.getDepH();
      if (xZoom < netW/2) xZoom = netW/2;
      if (xZoom+netW/2 > network.getDepW()) xZoom = network.getDepW()-netW/2;
      if (yZoom < netH/2) yZoom = netH/2;
      if (yZoom+netH/2 > network.getDepH()) yZoom = network.getDepH()-netH/2;
      ratioW = (double)this.getBounds().width/netW;
			ratioH = (double)this.getBounds().height/netH;
			repaint();
    } 
	}
	
	public void showFrame() {
		frame.pack();
		frame.setVisible(true);
	}
	
	//-------------------------Graphic stuff-------------------------
	public void resizedResponse() {
		if (netW > network.getDepW())
     	netW = network.getDepW();
    if (netH > network.getDepH())
     	netH = network.getDepH();
		simW = this.getBounds().width;
		simH = this.getBounds().height;
		ratioW = (double)simW/netW;
		ratioH = (double)simH/netH;
		repaint();
	}
	
	public void drawNode(Graphics2D gr2d, TNode n) {
		double realX = n.getLoc().x - xZoom + netW/2;
		double realY = n.getLoc().y - yZoom + netH/2;
		int simX = (int)(realX*ratioW);
		int simY = (int)((netH-realY)*ratioH);
		int radius = 10;
		int simRadW = (int)(radius*ratioW);
		if (simRadW > 15) simRadW = 15;
		int simRadH = (int)(radius*ratioH);
		if (simRadH > 15) simRadH = 15;
		Font font = new Font("Arial", Font.BOLD, simRadW);
		FontMetrics fm = getFontMetrics(font); 
		gr2d.setFont(font);
		Color textColor = TGraphic.getColor("#680000");
		Color fillColor = Color.gray;
		int sw;
		switch (n.getNodeType()) {
			case TNode.SENSOR:
				TSensor sensor = (TSensor)n;
				if (sensor.getType()==TSensor.DESTINATION)
					fillColor = TGraphic.getColor("#7A0101");
				else if (sensor.getType()==TSensor.FORWARDER)
					fillColor = Color.blue;
				else if (sensor.getType()==TSensor.REPLICATION)
					fillColor = Color.red;
				else if (sensor.getType()==TSensor.NORMAL)
					fillColor = Color.gray;
				gr2d.setColor(fillColor);
				gr2d.fillOval(simX-simRadW, simY-simRadH, 2*simRadW, 2*simRadH);
				gr2d.setColor(textColor);
				sw = fm.stringWidth(sensor.getRadio().getAddr());
				gr2d.drawString(sensor.getRadio().getAddr(), simX-sw/2, simY-simRadW);				
				break;
				
			case TNode.GATEWAY:
				TGateway gateway = (TGateway)n;
				int[] x = new int[3];
				int[] y = new int[3];
				x[0] = simX; y[0] = simY-simRadH;
				x[1] = simX-simRadW; y[1] = simY+simRadH;
				x[2] = simX+simRadW; y[2] = simY+simRadH;
				Polygon gwShape = new Polygon(x, y, 3);
				fillColor = Color.red;
				gr2d.setColor(fillColor);
				gr2d.fillPolygon(gwShape);
				gr2d.setColor(textColor);
				sw = fm.stringWidth(gateway.getRadio().getAddr());
				gr2d.drawString(gateway.getRadio().getAddr(), simX-sw/2, simY-simRadW);				
				break;
				
			default: break;
		}
	}

	@Override 
	public void paintComponent(Graphics g) {
		super.paintComponent(g);

		//Redraw my stuff
		Graphics2D gr2d = (Graphics2D)g;
		gr2d.setXORMode(Color.white);

		//Draw links
		Stroke thick = new BasicStroke(6);
		Stroke thin = new BasicStroke(1);
		gr2d.setColor(Color.black);
		for (int i=0; i<net.len(); i++) {
			for (int j=i+1; j<net.len(); j++) {
				TNode ni = (TNode)net.get(i);
				TNode nj = (TNode)net.get(j);
				if (TPoint.dist(ni.getLoc(), nj.getLoc()) <= ni.getRadio().getTX()) {
					int Xi = (int)((ni.getLoc().x-xZoom+netW/2)*ratioW);
					int Yi = (int)((netH-(ni.getLoc().y-yZoom+netH/2))*ratioH);
					int Xj = (int)((nj.getLoc().x-xZoom+netW/2)*ratioW);
					int Yj = (int)((netH-(nj.getLoc().y-yZoom+netH/2))*ratioH);
					/*gr2d.setStroke(thin);
					if (ni.getNodeType()==TNode.SENSOR) {
						TSensor sen = (TSensor)ni;
						if (sen.inRecord(nj.getAddr())) {
							gr2d.setStroke(thick);
							System.out.println("Im here");
						}
					}*/
					gr2d.drawLine(Xi, Yi, Xj, Yj);
				}
			}
		}

		//Draw nodes
		for (int i=0; i<net.len(); i++) {
			TNode n = (TNode)net.get(i);
			drawNode(gr2d, n);
		}
	}
}
